package code

import (
	"fmt"
	"sync"
)

var (
	// codes 包含一个错误代码到元数据的映射表
	codes   = map[int]Coder{}
	codeMux = &sync.Mutex{}
)

type Coder interface {
	// ErrorCode 错误码
	ErrorCode() int
	// Code 展示的错误码，是真正返回给客户端的错误码
	Code() int
	// HttpStatus 返回http的错误码
	HttpStatus() int
	// Message 返回错误信息
	Message() string
	// MessageCh 返回错误信息
	MessageCh() string
	// MessageF 返回格式化的信息
	MessageF(values ...any) string
	// MessageChF 返回格式化的信息
	MessageChF(values ...any) string
	// Messages 返回所有有的错误信息
	Messages() []string
	// MessagesF 返回所有信息格式化后的信息
	MessagesF(values ...any) []string
	// Reference 返回用户的详细文档
	Reference() string
}

// Register 用于注册自定义错误码。
// 如果注册的错误码已经存在，则会覆盖之前的错误码
func Register(coder Coder) {
	codeMux.Lock()
	defer codeMux.Unlock()
	codes[coder.ErrorCode()] = coder
}

// MustRegister 注册一个用户定义的错误代码。
// 如果相同的 Code 已经存在，它将会 panic
func MustRegister(coder Coder) {
	codeMux.Lock()
	defer codeMux.Unlock()
	if _, ok := codes[coder.ErrorCode()]; ok {
		panic(fmt.Sprintf("code : %d already exists", coder.ErrorCode()))
	}
	codes[coder.ErrorCode()] = coder
}

func GetByCode(errorCode int) (Coder, bool) {
	coder, ok := codes[errorCode]
	return coder, ok
}

func Get(errorCode int) Coder {
	return codes[errorCode]
}
